/******************************************************************************************************
Copyright (C) 2013 Mestrelab Research S.L. All rights reserved.

This file is part of the Mnova scripting toolkit.

Authorized users of MNova Software may use this file freely, but this file is provided AS IS
with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE.
*****************************************************************************************************/

/*globals settings, Dir, Application, DBPlugin, qsTr, MessageBox, Dialog, File, FileDialog, print, SpinBox, GroupBox, LineEdit, ProgressDialog, Str, TextStream, ToolButton, MnUi*/
/*jslint plusplus: true, indent: 4*/

function dbExportCSV() {
    "use strict";
    var db, dialog, sbFrom, sbTo, gbRange, leOutFile, tbOpenFile, gbOutFile,
        itemTypes, i, outFile, outStream, progress, count, cid, items, item, row, c,
        columns = [],
        fileSettingsKey = "Database/Export CSV/Last File",
        fileName = settings.value(fileSettingsKey, Dir.home() + "/output.csv");

    // Choose database
    Application.mainWindow.doAction("dbDatabaseOpen");
    if (!(DBPlugin.client.connected() && DBPlugin.client.database.length > 0)) {
        return;
    }

    // Check that we have something to export
    db = DBPlugin.client.definition(DBPlugin.client.database);
    if (db.records <= 0) {
        MessageBox.critical(qsTr("Database '{0}' is empty.".format(db.name)));
        return;
    }

    // Dialog for record range and output file
    dialog = new Dialog(qsTr("Export CSV"));
    dialog.onOpenFile = function () {
        var file = FileDialog.getSaveFileName("*.csv", "Select Output File", this.text);
        if (file.length > 0) {
            this.text = file;
        }
    };

    sbFrom = new SpinBox();
    sbFrom.minimum = 1;
    sbFrom.maximum = db.records;
    sbFrom.value = 1;

    sbTo = new SpinBox();
    sbTo.minimum = 1;
    sbTo.maximum = db.records;
    sbTo.value = sbTo.maximum;

    gbRange = new GroupBox();
    gbRange.title = qsTr("Select Records");
    gbRange.add(qsTr("From:"), sbFrom);
    gbRange.add(qsTr("To:"), sbTo);

    leOutFile = new LineEdit();
    leOutFile.label = qsTr("Output file:");
    leOutFile.text = fileName;

    tbOpenFile = new ToolButton();
    tbOpenFile.text = "...";
    tbOpenFile.clicked.connect(leOutFile, dialog.onOpenFile);

    gbOutFile = new GroupBox();
    gbOutFile.title = qsTr("Export to:");
    gbOutFile.add(leOutFile, tbOpenFile);

    dialog.add(gbRange);
    dialog.add(gbOutFile);

    if (!dialog.exec()) {
        return;
    }

    // Save settings
    fileName = leOutFile.text;
    settings.setValue(fileSettingsKey, fileName);

    // Open outFile
    outFile = new File(fileName);
    outFile.open(File.WriteOnly);
    outStream = new TextStream(outFile);

    // Write CSV header
    itemTypes = db.itemTypes();
    for (i = 0; i < itemTypes.length; i++) {
        columns = columns.concat(db.fields(itemTypes[i]));
    }
    columns = columns.filter(function unique(value, index, self) {  return self.indexOf(value) === index; });
    columns.sort();

    for (c = 0; c < columns.length; c++) {
        //print("" + c + ": " + columns[c]);
        if (c > 0) {
            outStream.write(",");
        }
        outStream.write(Str.linifyAndQuote(columns[c]));
    }
    outStream.writeln();

    // Export
    progress = new ProgressDialog();
    progress.setRange(sbFrom.value, sbTo.value + 1);
    progress.show();

    count = 0;
    for (cid = sbFrom.value; cid <= sbTo.value && !progress.wasCanceled; ++cid) {
        progress.value = cid;
        progress.labelText = qsTr("Exporting record {0} ({1} of {2})...").format(cid, cid - sbFrom.value + 1, sbTo.value - sbFrom.value + 1);
        Application.mainWindow.processEvents();

        // Retrieve record
        print("Retrieving record " + cid + "...");
        items = DBPlugin.getRecordItems(DBPlugin.client, cid);
        print("Retrieved " + items.length + " items from record id " + cid + ".");
        for (i = 0; i < items.length; i++) {
            item = items[i];
            //print(item);
            //print(JSON.stringify(item.fieldNames()));
            row = [];
            for (c = 0; c < columns.length; c++) {
                row.push(Str.linifyAndQuote(item.hasField(columns[c]) ? "{0}".format(item.field(columns[c])) : ""));
            }
            outStream.writeln(row.join(","));
            count++;
        }
    }
    outFile.close();
    progress.close();
    print("All done");
    MessageBox.information(qsTr("Exported {0} rows to {1}.").format(count, fileName));
}

if (this.MnUi && MnUi.scripts_db) {
    MnUi.scripts_db.scripts_db_ExportCSV = dbExportCSV;
}
